package com.dc.toolkit.json_fastjson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.dc.toolkit.json_fastjson.bo.Person;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.junit.Test;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

/**
 * Description: fastJson 测试 demo
 * @author: gdc
 * @date: 2021/5/19
 * @version 1.0
 */
public class FastJsonTest {


    private static final String JSON_OBJ_NOT_EXIST_DATE = "{\"isDel\":true,\"ID\":1,\"name\":\"张三\",\"age\":15}";
    private static final String JSON_OBJ_EXIST_DATE = "{\"isDel\":true,\"ID\":1,\"name\":\"张三\",\"age\":15,\"brithday\":\"2020-05-06\"}";
    private static final String JSON_LIST = "[{\"isDel\":true,\"ID\":3,\"name\":\"杨过\",\"age\":21},{\"isDel\":false,\"ID\":4,\"name\":\"小龙女\",\"age\":20,\"brithday\":\"2020-01-15\"}]";

    private static final Person OBJECT_PERSON = new Person().setId(1).setName("张三").setAge(15).setIsDel(true).setBrithday(LocalDate.of(2020, 5, 6));
    private static final Person OBJECT_PERSON_NOT_EXIST_DATE = new Person().setId(1).setName("张三").setAge(15).setIsDel(true);
    private static final List<Person> LIST_PERSON = Lists.newArrayList(
            new Person(3, "杨过", 21, null, true),
            new Person(4, "小龙女", 20, LocalDate.of(2020, 1, 15), false));

    /**
     * 测试               对象转 Json String
     */
    @Test
    public void testToJSONString(){
        // 当字段值为空时，序列号默认没有此字段
        String obj2JsonStr = JSON.toJSONString(OBJECT_PERSON);
        System.out.println("Object -> JsonStr: " + obj2JsonStr);

        System.out.println();

        // Map对象 转 JsonStr
        Map<String, Object> map = Maps.newHashMap();
        map.put("id", 2);
        map.put("name", "李四");
        map.put("age", 18);
        String map2JsonStr = JSON.toJSONString(map);
        System.out.println("Map -> JsonStr: " + map2JsonStr);

        System.out.println();

        // 对象列表 转 JsonStr
        String list2JsonStr = JSON.toJSONString(LIST_PERSON);
        System.out.println("List -> JsonStr: " + list2JsonStr);
    }

    /**
     * UseSingleQuotes:使用单引号而不是双引号,默认为false
     *
     * {"ID":1,"name":"张三","age":15,"brithday":"2020-05-06"}
     * {'ID':1,'name':'张三','age':15,'brithday':'2020-05-06'}
     */
    @Test
    public void testToJSONString_UseSingleQuotes() {
        System.out.println(JSONObject.toJSONString(OBJECT_PERSON));

        System.out.println("\n设置useSingleQuotes后：");
        System.out.println(JSONObject.toJSONString(OBJECT_PERSON, SerializerFeature.UseSingleQuotes));
    }

    /**
     * WriteMapNullValue:是否输出值为null的字段,默认为false
     *
     * {"ID":1,"name":"张三","age":15,"brithday":"2020-05-06"}
     * {"ID":1,"name":"张三","age":15,"brithday":"2020-05-06","list":null,"map":null}
     */
    @Test
    public void testToJSONString_WriteMapNullValue() {
        System.out.println(JSONObject.toJSONString(OBJECT_PERSON));

        System.out.println("\n设置WriteMapNullValue后：");
        System.out.println(JSONObject.toJSONString(OBJECT_PERSON, SerializerFeature.WriteMapNullValue));
    }

    /**
     * WriteNullListAsEmpty:List字段如果为null,输出为[],而非null
     *
     * {"ID":1,"name":"张三","age":15,"brithday":"2020-05-06"}
     * {"ID":1,"name":"张三","age":15,"brithday":"2020-05-06","list":[]}
     */
    @Test
    public void testToJSONString_WriteNullListAsEmpty() {
        System.out.println(JSONObject.toJSONString(OBJECT_PERSON));

        System.out.println("\n设置WriteNullListAsEmpty后：");
        System.out.println(JSONObject.toJSONString(OBJECT_PERSON, SerializerFeature.WriteNullListAsEmpty));
    }

    /**
     *  WriteNullStringAsEmpty:字符类型字段如果为null,输出为"",而非null
     *
     *  {"ID":1,"age":15,"brithday":"2020-05-06"}
     *  {"ID":1,"name":"","age":15,"brithday":"2020-05-06"}
     */
    @Test
    public void testToJSONString_WriteNullStringAsEmpty() {
        Person person = OBJECT_PERSON;
        person.setName(null);
        System.out.println(JSONObject.toJSONString(person));

        System.out.println("\n设置WriteNullStringAsEmpty后：");
        System.out.println(JSONObject.toJSONString(person, SerializerFeature.WriteNullStringAsEmpty));
    }

    /**
     * PrettyFormat:        JSON输出格式化
     *
     * {"ID":1,"name":"张三","age":15,"brithday":"2020-05-06"}
     * {
     * 	"ID":1,
     * 	"name":"张三",
     * 	"age":15,
     * 	"brithday":"2020-05-06"
     * }
     */
    @Test
    public void testToJSONString_PrettyFormat() {
        System.out.println(JSON.toJSONString(OBJECT_PERSON));
        System.out.println(JSON.toJSONString(OBJECT_PERSON, SerializerFeature.PrettyFormat));
    }

    /**
     * SortField:按字段名称排序后输出。默认为false
     * 这里使用的是fastjson：为了更好使用sort field martch优化算法提升parser的性能，fastjson序列化的时候，
     * 缺省把SerializerFeature.SortField特性打开了。
     * 反序列化的时候也缺省把SortFeidFastMatch的选项打开了。
     * 这样，如果你用fastjson序列化的文本，输出的结果是按照fieldName排序输出的，parser时也能利用这个顺序进行优化读取。
     * 这种情况下，parser能够获得非常好的性能。
     */
    @Test
    public void testToJSONString_SortField() {
        System.out.println(JSON.toJSONString(LIST_PERSON));
        System.out.println(JSON.toJSONString(LIST_PERSON, SerializerFeature.SortField));
    }

    /**
     * BeanToArray:将对象转为array输出
     *
     * [{"ID":3,"name":"杨过","age":21},{"ID":4,"name":"小龙女","age":20,"brithday":"2020-01-15"}]
     * [[3,"杨过",21,null,null,null],[4,"小龙女",20,"2020-01-15",null,null]]
     */
    @Test
    public void testToJSONString_BeanToArray() {
        System.out.println(JSON.toJSONString(LIST_PERSON));

        System.out.println("\n设置BeanToArray后：");
        System.out.println(JSON.toJSONString(LIST_PERSON, SerializerFeature.BeanToArray));
    }

    /**
     * 自定义
     *  1、格式化输出
     *  2、显示值为null的字段
     *  3、将为null的字段值显示为""
     *  4、DisableCircularReferenceDetect:消除循环引用
     *
     * {"ID":1,"age":15}
     * {
     * 	"list":[],
     * 	"map":null,
     * 	"ID":1,
     * 	"name":"",
     * 	"age":15,
     * 	"brithday":null
     * }
     */
    @Test
    public void testToJSONString_ShowJsonBySelf() {
        OBJECT_PERSON.setName(null);
        OBJECT_PERSON.setBrithday(null);
        OBJECT_PERSON.setList(null);
        OBJECT_PERSON.setMap(null);
        System.out.println(JSON.toJSONString(OBJECT_PERSON));

        System.out.println("\n自定义后的输出：");
        System.out.println(JSON.toJSONString(OBJECT_PERSON,
                SerializerFeature.PrettyFormat,                         // 格式化
                SerializerFeature.WriteMapNullValue,                    // 将Map字段，如果为null,输出为{}
                SerializerFeature.WriteNullStringAsEmpty,               // 将null的字段值显示为""
                SerializerFeature.DisableCircularReferenceDetect,       // 消除循环引用
                SerializerFeature.WriteNullListAsEmpty));               // List字段如果为null,输出为[]
    }




    // ---------------------------------------------------------------------------------------





    /**
     * 测试               JSON字符串 转 对象
     */
    @Test
    public void testParseObject(){
        // Json字符串 转 对象（isDel字段不参数反序列化）
        Person person = JSON.parseObject(JSON_OBJ_EXIST_DATE, Person.class);
        System.out.println(person);

        // Json字符串 转 Json对象
        JSONObject jsonObject = JSON.parseObject(JSON_OBJ_EXIST_DATE);
        System.out.println(jsonObject);
        System.out.println(jsonObject.getString("name") + "--" + jsonObject.getInteger("age"));
    }

    /**
     * 测试               JSON字符串 转 (List 或 JSONArray)
     */
    @Test
    public void testParseArray(){
        // Json字符串转对象（isDel字段不参数反序列化）
        List<Person> persons = JSON.parseArray(JSON_LIST, Person.class);
        System.out.println(persons);

        JSONArray jsonArray = JSON.parseArray(JSON_LIST);
        System.out.println(jsonArray);
        jsonArray.forEach(jsonObj -> {
            JSONObject jsonObject = ((JSONObject) jsonObj);
            System.out.println(jsonObject.getString("name") + "--" + jsonObject.getInteger("age"));
        });
    }

    /**
     * 测试               JSON字符串 转 （JavaBean_obj、JavaBean_List）
     */
    @Test
    public void testParseObject_By_TypeReference(){

        // JSON 转 对象
        Person person = JSON.parseObject(JSON_OBJ_EXIST_DATE, new TypeReference<Person>() {
        });
        System.out.println("JSON 转 对象: " + person);

        // JSON 转 列表
        List<Person> persons = JSON.parseObject(JSON_LIST, new TypeReference<List<Person>>() {
        });
        System.out.println("JSON 转 列表: " + persons);

        // JSON 转 List<Map>
        List<Map<String, Object>> list2=JSON.parseObject(JSON_LIST,new TypeReference<List<Map<String,Object>>>(){});
        System.out.println("JSON 转 List<Map>: " + list2);
    }





}
